

#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <stdarg.h>
#include <pthread.h>
#include <arpa/inet.h>

#include "log.h"
#include "bitmap.h"
#include "list.h"
#include "rbtree.h"
#include "acl.h"
#include "aclmgr.h"


#define BIT_COUNT 32

#define SHORTCUT_CNT 8

typedef struct tagBITMAP_MATCH_S
{
    BITMAP_EX_S stHead;
    BITMAP_S *pstBitmap;
} BITMAP_MATCH_S;
#define RESERVED_BITMAP_CNT  2

#define BITMAP_BASE  	0x80000000U
#define BITMAP_SET(X)   (BITMAP_BASE>>X)

typedef struct tagRbtRuleSummary
{
    struct rb_node stNode;
    unsigned int uiPriority;
} RBT_RULE_SUMMARY_S;

typedef struct tagRuleMatch
{
    unsigned int uiBitmapID;
    struct rb_root stMatchList;
} RULE_MATCH_S;

typedef struct tagRbtIPv4Item
{
	struct rb_node stNode;
    IPV4_RANGE_S stKeyRange;
    IPV4_RANGE_S stAdjustRange;
    struct rb_root stMatchList;
    unsigned int uiFlag;
} RBT_IPV4_ITEM_S;

typedef struct tagRbtBitmapEx
{
	struct rb_node stNode;    
    unsigned int uiBitmapID;
    BITMAP_EX_S *pstBitmapEx;
} RBT_BITMAP_EX_S;

typedef struct tagSwiftIPv4
{
    RULE_MATCH_S stAnyRoot;
    struct rb_root stCfgIPv4List;
    struct rb_root stIpv4Match;
} SWIFT_IPV4_S;

typedef struct tagRbtIPv4MatchNode 
{
	struct rb_node stNode;
	IPV4_RANGE_S stKey;
	RULE_MATCH_S stMatch;
} RBT_IPV4_MATCH_NODE_S;

typedef struct tagSwiftForward
{
    unsigned int uiKeyMask;
    unsigned int uiRuleCount;
    RULE_SUMMARY_S *pstRuleArray;
    unsigned int uiBitmapIDMax;
    BITMAP_EX_S **ppstBitmapArray;  // index 0 reserved
    struct rb_root stBitmapRbt;     // temp
    SWIFT_IPV4_S *pstSrcIPv4;    
    SWIFT_IPV4_S *pstDestIPv4;  
} SWIFT_FWD_S;


pthread_rwlock_t lockMatch;
SWIFT_FWD_S *g_pstSwiftFwd;
void destroy_swift(SWIFT_FWD_S *pstSwift);


BITMAP_EX_S *BITMAP_EX_Create(struct rb_root *pstRbtMatchRoot)
{
    unsigned int uiLocation = 0;
    unsigned int uiTemporaryLoc = 0;
    unsigned int uiTemporaryMap = 0;
    unsigned int uiMaxBitmapCnt = 0;
    unsigned int uiMaxBitmapLen = 0;
    RBT_RULE_SUMMARY_S *pstSummary = NULL;
    struct rb_node *pstRbtMatchNode = NULL;
    BITMAP_EX_S *pstTemporaryBitmapEx = NULL;
    BITMAP_S *pstCurrentBitmap = NULL;
    
    uiMaxBitmapCnt = RULE_COUNT()/BIT_COUNT + RESERVED_BITMAP_CNT;
    uiMaxBitmapLen = sizeof(BITMAP_EX_S) + uiMaxBitmapCnt * sizeof(BITMAP_S);
    pstTemporaryBitmapEx = (BITMAP_EX_S *)zalloc(uiMaxBitmapLen);
    if (NULL == pstTemporaryBitmapEx)
    {
        return NULL;
    }

    pstCurrentBitmap = pstTemporaryBitmapEx->astBitmap;
    for (pstRbtMatchNode = rb_first(pstRbtMatchRoot); pstRbtMatchNode; pstRbtMatchNode = rb_next(pstRbtMatchNode)) 
    {
        pstSummary = rb_entry(pstRbtMatchNode, RBT_RULE_SUMMARY_S, stNode);
        if (pstSummary->uiPriority > RULE_RESERVED_PRIORITY)
        {
            uiLocation = pstSummary->uiPriority - 1;
            uiTemporaryLoc = (uiLocation/BIT_COUNT) + 1;
            uiTemporaryMap = BITMAP_SET(uiLocation%BIT_COUNT);
            if (0 == pstCurrentBitmap->uiLoc)
            {
                pstCurrentBitmap->uiLoc = uiTemporaryLoc;
                pstCurrentBitmap->uiValue = uiTemporaryMap;
                pstTemporaryBitmapEx->uiCount++;
            }
            else if (uiTemporaryLoc == pstCurrentBitmap->uiLoc)
            {
                pstCurrentBitmap->uiValue |= uiTemporaryMap;
            }
            else if (uiTemporaryLoc > pstCurrentBitmap->uiLoc)
            {
                pstCurrentBitmap++;
                pstCurrentBitmap->uiLoc = uiTemporaryLoc;
                pstCurrentBitmap->uiValue = uiTemporaryMap;
                pstTemporaryBitmapEx->uiCount++;
            }
        }
    }

    pstCurrentBitmap++;
    pstCurrentBitmap->uiLoc = BITMAP_LOC_INVALID_NEW;
    pstCurrentBitmap->uiValue = BITMAP_VAL_INVALID_NEW;
    
    return pstTemporaryBitmapEx;
}

inline int BITMAP_EX_Compare(BITMAP_EX_S *pstBitmapEx1, BITMAP_EX_S *pstBitmapEx2)
{
    unsigned int uiLoop = 0;
    
    if (pstBitmapEx1->uiCount < pstBitmapEx2->uiCount)
    {
        return RBT_LESS;
    }
    else if (pstBitmapEx1->uiCount > pstBitmapEx2->uiCount)
    {
        return RBT_GREAT;
    }
    else
    {
        for (uiLoop = 0; uiLoop < pstBitmapEx1->uiCount; uiLoop++)
        {
            if (pstBitmapEx1->astBitmap[uiLoop].uiLoc < pstBitmapEx2->astBitmap[uiLoop].uiLoc)
            {
                return RBT_LESS;
            }
            if (pstBitmapEx1->astBitmap[uiLoop].uiLoc > pstBitmapEx2->astBitmap[uiLoop].uiLoc)
            {
                return RBT_GREAT;
            }
            if (pstBitmapEx1->astBitmap[uiLoop].uiValue < pstBitmapEx2->astBitmap[uiLoop].uiValue)
            {
                return RBT_LESS;
            }
            if (pstBitmapEx1->astBitmap[uiLoop].uiValue > pstBitmapEx2->astBitmap[uiLoop].uiValue)
            {
                return RBT_GREAT;
            }
        }
    }   

    return RBT_EQUAL;
}

BITMAP_EX_S *BITMAP_EX_Formalize(BITMAP_EX_S *pstTemporaryBitmapEx)
{
    unsigned int uiFormalBitmapCnt = 0;
    unsigned int uiFormalBitmapLen = 0;
    BITMAP_EX_S *pstFormalBitmapEx = NULL;
    
	uiFormalBitmapCnt = pstTemporaryBitmapEx->uiCount + RESERVED_BITMAP_CNT;
	uiFormalBitmapLen = sizeof(BITMAP_EX_S) + uiFormalBitmapCnt * sizeof(BITMAP_S);
	pstFormalBitmapEx = (BITMAP_EX_S *)zalloc(uiFormalBitmapLen);
	if (NULL != pstFormalBitmapEx)
	{
		memcpy(pstFormalBitmapEx, pstTemporaryBitmapEx, uiFormalBitmapLen);
	}

    return pstFormalBitmapEx;
}

static inline unsigned int SWIFT_GET_KEYMASK(SWIFT_FWD_S *pstSwift)
{
	return pstSwift->uiKeyMask;
}

static inline void SWIFT_SET_KEYMASK(SWIFT_FWD_S *pstSwift, unsigned int uiKeyMask)
{
	pstSwift->uiKeyMask |= uiKeyMask;
}

static inline bool SWIFT_TEST_KEYMASK(unsigned int uiKeyMask, unsigned int uiTestMask)
{
	return (uiKeyMask & uiTestMask) ? true:false;
}

void RBT_SummaryNodeFree(struct rb_node *pNode)
{
	RBT_RULE_SUMMARY_S *pstSummaryNode = rb_entry(pNode, RBT_RULE_SUMMARY_S, stNode);
    free(pstSummaryNode);
}

int RBT_SummaryNodeCompare(struct rb_node *pstNew, const struct rb_node *pstMember)
{
	RBT_RULE_SUMMARY_S *pstNewNode = rb_entry(pstNew, RBT_RULE_SUMMARY_S, stNode);
	RBT_RULE_SUMMARY_S *pstMemberNode = rb_entry(pstMember, RBT_RULE_SUMMARY_S, stNode);

	if (pstNewNode->uiPriority < pstMemberNode->uiPriority)
	{
		return RBT_LESS;
	}
	else if (pstNewNode->uiPriority > pstMemberNode->uiPriority)
	{
		return RBT_GREAT;
	}
	else
	{
		return RBT_EQUAL;
	}
}

int RBT_IPv4MatchNodeCompare(struct rb_node *pstNew, const struct rb_node *pstMember)
{
	RBT_IPV4_MATCH_NODE_S *pstNewNode = rb_entry(pstNew, RBT_IPV4_MATCH_NODE_S, stNode);
	RBT_IPV4_MATCH_NODE_S *pstMemberNode = rb_entry(pstMember, RBT_IPV4_MATCH_NODE_S, stNode);

	if ((pstNewNode->stKey.ipStart < pstMemberNode->stKey.ipStart) ||
		((pstNewNode->stKey.ipStart == pstMemberNode->stKey.ipStart) &&
	     (pstNewNode->stKey.ipEnd < pstMemberNode->stKey.ipEnd)))
	{
		return RBT_LESS;
	}
	else if ((pstNewNode->stKey.ipStart > pstMemberNode->stKey.ipStart) ||
 			 ((pstNewNode->stKey.ipStart == pstMemberNode->stKey.ipStart) &&
 		      (pstNewNode->stKey.ipEnd > pstMemberNode->stKey.ipEnd)))
	{
		return RBT_GREAT;
	}
	else
	{
		return RBT_EQUAL;
	}
}

void RBT_IPv4MatchNodeFree(struct rb_node *pNode)
{
	RBT_IPV4_MATCH_NODE_S *pstIPv4MatchNode = rb_entry(pNode, RBT_IPV4_MATCH_NODE_S, stNode);
    rb_destory(&(pstIPv4MatchNode->stMatch.stMatchList), RBT_SummaryNodeFree);
    free(pstIPv4MatchNode);
}

void RBT_IPv4RangeNodeFree(struct rb_node *pNode)
{
	RBT_IPV4_ITEM_S *pstNode = rb_entry(pNode, RBT_IPV4_ITEM_S, stNode);
    rb_destory(&(pstNode->stMatchList), RBT_SummaryNodeFree);
	free(pstNode);
}

int RBT_IPv4RangeCompare(struct rb_node *pstNew, const struct rb_node *pstMember)
{
	RBT_IPV4_ITEM_S *pstNewNode = rb_entry(pstNew, RBT_IPV4_ITEM_S, stNode);
	RBT_IPV4_ITEM_S *pstMemberNode = rb_entry(pstMember, RBT_IPV4_ITEM_S, stNode);

	if ((pstNewNode->stKeyRange.ipStart < pstMemberNode->stKeyRange.ipStart) ||
		((pstNewNode->stKeyRange.ipStart == pstMemberNode->stKeyRange.ipStart) &&
	     (pstNewNode->stKeyRange.ipEnd < pstMemberNode->stKeyRange.ipEnd)))
	{
		return RBT_LESS;
	}
	else if ((pstNewNode->stKeyRange.ipStart > pstMemberNode->stKeyRange.ipStart) ||
 			 ((pstNewNode->stKeyRange.ipStart == pstMemberNode->stKeyRange.ipStart) &&
 		      (pstNewNode->stKeyRange.ipEnd > pstMemberNode->stKeyRange.ipEnd)))
	{
		return RBT_GREAT;
	}
	else
	{
		return RBT_EQUAL;
	}
}

int RBT_BitmapExCompare(struct rb_node *pstNew, const struct rb_node *pstMember)
{
	RBT_BITMAP_EX_S *pstNewNode = rb_entry(pstNew, RBT_BITMAP_EX_S, stNode);
	RBT_BITMAP_EX_S *pstMemberNode = rb_entry(pstMember, RBT_BITMAP_EX_S, stNode);

    if (NULL == pstNewNode->pstBitmapEx)
    {
        if (NULL == pstMemberNode->pstBitmapEx)
        {
            return RBT_EQUAL;
        }
        else
        {
            return RBT_LESS;
        }
    }
    else
    {
        if (NULL == pstMemberNode->pstBitmapEx)
        {
            return RBT_GREAT;
        }
        else
        {
            return BITMAP_EX_Compare(pstNewNode->pstBitmapEx, pstMemberNode->pstBitmapEx);
        }
    }
}

void RBT_BitmapExNodeFree(struct rb_node *pNode)
{
	RBT_BITMAP_EX_S *pstRbtNode = rb_entry(pNode, RBT_BITMAP_EX_S, stNode);
	if (NULL != pstRbtNode->pstBitmapEx)
	{
	    free(pstRbtNode->pstBitmapEx);
	    pstRbtNode->pstBitmapEx = NULL;
	}
;   free(pstRbtNode);
}

void RBT_BitmapExShellFree(struct rb_node *pNode)
{
	RBT_BITMAP_EX_S *pstRbtNode = rb_entry(pNode, RBT_BITMAP_EX_S, stNode);
;   free(pstRbtNode);
}

// IPv4 Match
int RBT_IPv4MatchRange(struct rb_node *pstNew, const struct rb_node *pstMember)
{
	RBT_IPV4_MATCH_NODE_S *pstNewNode = rb_entry(pstNew, RBT_IPV4_MATCH_NODE_S, stNode);
	RBT_IPV4_MATCH_NODE_S *pstMemberNode = rb_entry(pstMember, RBT_IPV4_MATCH_NODE_S, stNode);

	if ((pstNewNode->stKey.ipStart >= pstMemberNode->stKey.ipStart) &&
		(pstNewNode->stKey.ipStart <= pstMemberNode->stKey.ipEnd))
	{
		return RBT_EQUAL;
	}
	else if (pstNewNode->stKey.ipStart < pstMemberNode->stKey.ipStart)
	{
		return RBT_LESS;
	}
	else
	{
		return RBT_GREAT;
	}
}

void print_bitmap_ex(unsigned int uiBitmapID, BITMAP_EX_S *pstBitmapEx)
{
	unsigned int uiIndex;

	if (NULL != pstBitmapEx)
	{
		for (uiIndex=0; uiIndex<pstBitmapEx->uiCount; uiIndex++)
		{
		    BITMAP_S stBitmap = pstBitmapEx->astBitmap[uiIndex];
			LOGGER("	[%u]={%05u, %08X}", uiBitmapID, stBitmap.uiLoc, stBitmap.uiValue);
		}
	}
}

void print_all_bitmap_ex(SWIFT_FWD_S *pstNewSwift)
{
	unsigned int uiBitmapID;
	BITMAP_EX_S *pstBitmapEx = NULL;

    if (NULL != pstNewSwift->ppstBitmapArray)
    {
        for (uiBitmapID = 0; uiBitmapID <= pstNewSwift->uiBitmapIDMax; uiBitmapID++)
		{
            pstBitmapEx = pstNewSwift->ppstBitmapArray[uiBitmapID];
            if (NULL != pstBitmapEx)
            {
                print_bitmap_ex(uiBitmapID, pstBitmapEx);
            }
		}
    }
}

void print_all_ipv4_cfglist(const char *pcLabel, struct rb_root* pstCfgIPv4List)
{
	IPV4_RANGE_S stIPv4Item;
	struct rb_node *pstRbtObjNode = NULL;
	struct rb_node *pstRbtMatchNode = NULL;
	RBT_IPV4_ITEM_S *pstObjectNode = NULL;
	RBT_RULE_SUMMARY_S *pstSummary = NULL;
    char szIpStart[IPV4_MAX_LEN+1] = { 0 };
    char szIpEnd[IPV4_MAX_LEN+1] = { 0 };

	for (pstRbtObjNode = rb_first(pstCfgIPv4List); pstRbtObjNode; pstRbtObjNode = rb_next(pstRbtObjNode)) 
	{
		pstObjectNode = rb_entry(pstRbtObjNode, RBT_IPV4_ITEM_S, stNode);
		stIPv4Item = pstObjectNode->stAdjustRange;

        ipv4_to_string(ntohl(stIPv4Item.ipStart), szIpStart, sizeof(szIpStart));
        ipv4_to_string(ntohl(stIPv4Item.ipEnd), szIpEnd, sizeof(szIpEnd));
		LOGGER("[%s] IPV4_CFG %s to %s!", pcLabel, szIpStart, szIpEnd);
		LOGGER(" {");
		for (pstRbtMatchNode = rb_first(&(pstObjectNode->stMatchList)); pstRbtMatchNode; pstRbtMatchNode = rb_next(pstRbtMatchNode)) 
		{
			pstSummary = rb_entry(pstRbtMatchNode, RBT_RULE_SUMMARY_S, stNode);
			LOGGER("	%u,", pstSummary->uiPriority);
		}
		LOGGER(" }");
	}
}

unsigned int is_swift_ready(SWIFT_FWD_S *pstSwift)
{
	if (NULL == pstSwift->pstRuleArray)
	{
		return ERROR_FAILED;
	}

	if (NULL == pstSwift->pstSrcIPv4)
	{
		return ERROR_FAILED;
	}

	if (NULL == pstSwift->pstDestIPv4)
	{
		return ERROR_FAILED;
	}
    
    return ERROR_SUCCESS;
}

void init_swift_ipv4(SWIFT_IPV4_S *pstSwiftIPv4)
{
    pstSwiftIPv4->stAnyRoot.stMatchList = RB_ROOT;
    pstSwiftIPv4->stCfgIPv4List = RB_ROOT;
    pstSwiftIPv4->stIpv4Match = RB_ROOT;
}

SWIFT_FWD_S* alloc_swift()
{
    unsigned int uiRuleCount;
	SWIFT_FWD_S *pstNewSwift = NULL;
    
    pstNewSwift = (SWIFT_FWD_S *)zalloc(sizeof(SWIFT_FWD_S));
    if (NULL == pstNewSwift)
    {
        return NULL;
    }

    uiRuleCount = RULE_COUNT();
    pstNewSwift->uiRuleCount = uiRuleCount;
    pstNewSwift->pstRuleArray = (RULE_SUMMARY_S *)zalloc((uiRuleCount+1)*sizeof(RULE_SUMMARY_S));
    pstNewSwift->uiBitmapIDMax = 0;
    pstNewSwift->ppstBitmapArray = NULL;
    pstNewSwift->stBitmapRbt = RB_ROOT;
    pstNewSwift->pstSrcIPv4 = (SWIFT_IPV4_S *)zalloc(sizeof(SWIFT_IPV4_S));
    pstNewSwift->pstDestIPv4 = (SWIFT_IPV4_S *)zalloc(sizeof(SWIFT_IPV4_S));
    /*    
    for (enObject = OBJECT_1; enObject < OBJECT_MAX; enObject++)
    {
    	pstNewSwift->apstQuickObj[enObject] = (QUICK_OBJECT_S *)zalloc(sizeof(QUICK_OBJECT_S));
    }
    */    
    if (ERROR_SUCCESS != is_swift_ready(pstNewSwift))
    {
        destroy_swift(pstNewSwift);
        return NULL;
    }

    init_swift_ipv4(pstNewSwift->pstSrcIPv4);  
    init_swift_ipv4(pstNewSwift->pstDestIPv4);  
	/*
	for (enObject = OBJECT_1; enObject < OBJECT_MAX; enObject++)
    {
    	QUICK_INIT_OBJ(pstNewSwift->apstQuickObj[enObject]);
    }
    */

    return pstNewSwift;
}

void prepare_new_swift(SWIFT_FWD_S *pstNewSwift)
{
	RULE_S *pstNode = NULL;
    RULE_S *pstNext = NULL;
    struct list_head *pstRuleList = RULE_LIST();
    RULE_SUMMARY_S *pstRuleArray = NULL;
    struct rb_root *pstRbtIpv4Root = NULL;
    
	list_for_each_entry_safe(pstNode, pstNext, pstRuleList, stNode)
    {
        pstRuleArray = &(pstNewSwift->pstRuleArray[pstNode->uiPriority]);
        pstRuleArray->uiPriority = pstNode->uiPriority;
        strlcpy(pstRuleArray->szRuleName, pstNode->szRuleName, sizeof(pstRuleArray->szRuleName));
		
        pstRbtIpv4Root = &(pstNode->stSrcIPv4Rbt);
        if (true != rb_is_emplty(pstRbtIpv4Root))
		{
			SWIFT_SET_KEYMASK(pstNewSwift, RULE_KEY_SIP);
		}
		pstRbtIpv4Root = &(pstNode->stDstIPv4Rbt);
        if (true != rb_is_emplty(pstRbtIpv4Root))
		{
			SWIFT_SET_KEYMASK(pstNewSwift, RULE_KEY_DIP);
		}
    }
}

void destory_swift_ipv4(SWIFT_IPV4_S *pstSwiftIPv4)
{
    rb_destory(&(pstSwiftIPv4->stAnyRoot.stMatchList), RBT_SummaryNodeFree);
    rb_destory(&(pstSwiftIPv4->stCfgIPv4List), RBT_IPv4RangeNodeFree);
    rb_destory(&(pstSwiftIPv4->stIpv4Match), RBT_IPv4MatchNodeFree);
}

void destroy_swift(SWIFT_FWD_S *pstSwift)
{
	unsigned int uiLoop = 0;

    if (NULL != pstSwift)
    {
    	if (NULL != pstSwift->pstRuleArray)
    	{
	    	free(pstSwift->pstRuleArray);
	    	pstSwift->pstRuleArray = NULL;
    	}
    	
    	if (NULL != pstSwift->ppstBitmapArray)
    	{
    	    for (uiLoop = 0; uiLoop <= pstSwift->uiBitmapIDMax; uiLoop++)
    	    {
    	        if (NULL != pstSwift->ppstBitmapArray[uiLoop])
    	        {
    	            free(pstSwift->ppstBitmapArray[uiLoop]);
    	        }
    	    }
	    	free(pstSwift->ppstBitmapArray);
	    	pstSwift->ppstBitmapArray = NULL;
    	}
    	
        if (NULL != pstSwift->pstSrcIPv4)
        {
        	destory_swift_ipv4(pstSwift->pstSrcIPv4);
        	free(pstSwift->pstSrcIPv4);
        	pstSwift->pstSrcIPv4 = NULL;
        }

        if (NULL != pstSwift->pstDestIPv4)
        {
        	destory_swift_ipv4(pstSwift->pstDestIPv4);
        	free(pstSwift->pstDestIPv4);
        	pstSwift->pstDestIPv4 = NULL;
        }

        rb_destory(&(pstSwift->stBitmapRbt), RBT_BitmapExNodeFree);
        
        free(pstSwift);
    }
}

IPV4_RANGE_S caculate_ipv4_unique_range(struct rb_root *pstCfgIPv4List)
{
    IPV4_RANGE_S stUniqueRange;
    IPV4_RANGE_S stIPv4Loop;
    struct rb_node *pstRbtObjNode = NULL;
    RBT_IPV4_ITEM_S *pstIPv4Node = NULL;

	pstRbtObjNode = rb_first(pstCfgIPv4List);
	pstIPv4Node = rb_entry(pstRbtObjNode, RBT_IPV4_ITEM_S, stNode);
	stUniqueRange = pstIPv4Node->stAdjustRange;
    if (stUniqueRange.ipStart == stUniqueRange.ipEnd)
    {
        return stUniqueRange;
    }

    for (pstRbtObjNode = rb_next(pstRbtObjNode); pstRbtObjNode; pstRbtObjNode = rb_next(pstRbtObjNode))
    {
    	stIPv4Loop = pstIPv4Node->stAdjustRange;
        if (stIPv4Loop.ipStart == stUniqueRange.ipStart)
        {
            continue;
        }
        else if ((stIPv4Loop.ipStart > stUniqueRange.ipStart) &&
                 (stIPv4Loop.ipStart <= stUniqueRange.ipEnd))
        {
            stUniqueRange.ipEnd = stIPv4Loop.ipStart - 1;
            break;
        }
        else if (stIPv4Loop.ipStart > stUniqueRange.ipEnd)
        {
            break;
        }
    }

    return stUniqueRange;
}

unsigned int append_rule_to_matchlist(struct rb_root *pstRbtRoot, unsigned int uiPriority)
{
    RBT_RULE_SUMMARY_S *pstRbtSummary = NULL;

    pstRbtSummary = (RBT_RULE_SUMMARY_S *)zalloc(sizeof(RBT_RULE_SUMMARY_S));
    if (NULL == pstRbtSummary)
    {
        return ERROR_NONE_MEMORY;
    }
        
    pstRbtSummary->uiPriority = uiPriority;
    if (rb_add(&(pstRbtSummary->stNode), pstRbtRoot, RBT_SummaryNodeCompare))
    {
        RBT_SummaryNodeFree(&(pstRbtSummary->stNode)); // possible
    }

    return ERROR_SUCCESS;
}

unsigned int create_and_insert_to_cfglist(IPV4_RANGE_S stIPv4Range, struct rb_root *pstCfgIPv4List)
{
	RBT_IPV4_ITEM_S *pstIpv4Item = NULL;
	
	pstIpv4Item = (RBT_IPV4_ITEM_S *)zalloc(sizeof(RBT_IPV4_ITEM_S));
	if (NULL == pstIpv4Item)
	{
		return ERROR_NONE_MEMORY;
	}

	pstIpv4Item->stKeyRange = stIPv4Range;
	pstIpv4Item->stAdjustRange = stIPv4Range;
	pstIpv4Item->stMatchList = RB_ROOT;
	if (rb_add(&(pstIpv4Item->stNode), pstCfgIPv4List, RBT_IPv4RangeCompare))
	{
		free(pstIpv4Item);
	}

	return ERROR_SUCCESS;
}

unsigned int append_ipv4_to_cfglist(RULE_S *pstNode, IPV4_RANGE_S stIPv4Range, struct rb_root* pstCfgIPv4List)
{
	unsigned int uiRet = ERROR_SUCCESS;
	struct rb_node *pstRbtNode = NULL;
	RBT_IPV4_ITEM_S *pstIpv4Item = NULL; 
	RBT_IPV4_ITEM_S stItemFind; 

	stItemFind.stKeyRange = stIPv4Range;
	pstRbtNode = rb_find(&(stItemFind.stNode), pstCfgIPv4List, RBT_IPv4RangeCompare);
	if (NULL == pstRbtNode)
	{
		uiRet = create_and_insert_to_cfglist(stIPv4Range, pstCfgIPv4List);
		if (ERROR_SUCCESS != uiRet)
		{
			return uiRet;
		}
		// Retry find!
		pstRbtNode = rb_find(&(stItemFind.stNode), pstCfgIPv4List, RBT_IPv4RangeCompare);
		if (NULL == pstRbtNode)
		{
			return ERROR_NOT_EXIST;
		}
	}

	pstIpv4Item = rb_entry(pstRbtNode, RBT_IPV4_ITEM_S, stNode);
	uiRet = append_rule_to_matchlist(&(pstIpv4Item->stMatchList), pstNode->uiPriority);
	
    return uiRet;
}

unsigned int append_match_list_to_unique(struct rb_root* pstMatchList, struct rb_root* pstUniqueList)
{
    unsigned int ulRet = ERROR_SUCCESS;
    struct rb_node *pstRbtMatchNode = NULL;
    RBT_RULE_SUMMARY_S *pstSummary = NULL;

    for (pstRbtMatchNode = rb_first(pstMatchList); pstRbtMatchNode; pstRbtMatchNode = rb_next(pstRbtMatchNode)) 
	{
		pstSummary = rb_entry(pstRbtMatchNode, RBT_RULE_SUMMARY_S, stNode);
		ulRet = append_rule_to_matchlist(pstUniqueList, pstSummary->uiPriority);
		if (ERROR_SUCCESS != ulRet)
        {
            return ulRet;
        }
	}

	return ERROR_SUCCESS;
}

unsigned int append_ipv4_to_adjust(IPV4_RANGE_S *pstKeyRange, struct rb_root *pstNeedAdjust)
{
	RBT_IPV4_S *pstIpv4Node = NULL;
	
	pstIpv4Node = (RBT_IPV4_S*)RBT_Ipv4NodeAlloc(pstKeyRange->ipStart, pstKeyRange->ipEnd);
	if (NULL == pstIpv4Node)
	{
		return ERROR_NONE_MEMORY;
	}
	
	if (rb_add(&(pstIpv4Node->stNode), pstNeedAdjust, RBT_Ipv4NodeCompare))
	{
		RBT_Ipv4NodeFree(&(pstIpv4Node->stNode));
	}

	return ERROR_SUCCESS;
}

unsigned int adjust_ipv4_cfglist(struct rb_root *pstWaitAdjust, struct rb_root *pstCfgIPv4List)
{
	struct rb_node *pstRbtNode = NULL;
	RBT_IPV4_S *pstIpv4Node = NULL;
	struct rb_node *pstRbtObjectNode = NULL;
	RBT_IPV4_ITEM_S *pstIPv4ItemNode = NULL;
	RBT_IPV4_ITEM_S stIPv4ItemFind;
	
    for (pstRbtNode = rb_first(pstWaitAdjust); pstRbtNode; pstRbtNode = rb_next(pstRbtNode)) 
	{
		pstIpv4Node = rb_entry(pstRbtNode, RBT_IPV4_S, stNode);
		stIPv4ItemFind.stKeyRange = pstIpv4Node->stIpv4;
		pstRbtObjectNode = rb_find(&(stIPv4ItemFind.stNode), pstCfgIPv4List, RBT_IPv4RangeCompare);
		if (NULL != pstRbtNode)
		{
			pstIPv4ItemNode = rb_entry(pstRbtObjectNode, RBT_IPV4_ITEM_S, stNode);
			rb_erase(&(pstIPv4ItemNode->stNode), pstCfgIPv4List);
			if (0 == pstIPv4ItemNode->uiFlag)
			{
				pstIPv4ItemNode->stKeyRange = pstIPv4ItemNode->stAdjustRange;
				if (rb_add(&(pstIPv4ItemNode->stNode), pstCfgIPv4List, RBT_IPv4RangeCompare))
				{
					RBT_IPv4RangeNodeFree(&(pstIPv4ItemNode->stNode));
					return ERROR_CONFLICT;
				}
			}
            else
            {
                RBT_IPv4RangeNodeFree(&(pstIPv4ItemNode->stNode));
            }
		}
    }

    return ERROR_SUCCESS;
}

unsigned int append_bitmap_ex_to_swift(BITMAP_EX_S *pstBitmapEx, SWIFT_FWD_S *pstNewSwift)
{
    struct rb_node *pstRbtNode = NULL;
    struct rb_root *pstBitmapRbt = &pstNewSwift->stBitmapRbt;
    RBT_BITMAP_EX_S stItemFind; 
    RBT_BITMAP_EX_S *pstNewBitmapEx = NULL; 

    stItemFind.pstBitmapEx = pstBitmapEx;
    pstRbtNode = rb_find(&(stItemFind.stNode), pstBitmapRbt, RBT_BitmapExCompare);
    if (NULL == pstRbtNode)
    {
        pstNewBitmapEx = (RBT_BITMAP_EX_S *)zalloc(sizeof(RBT_BITMAP_EX_S));
        if (NULL == pstNewBitmapEx)
        {
            return BITMAP_LOC_INVALID_NEW;
        }
        pstNewBitmapEx->uiBitmapID = (pstNewSwift->uiBitmapIDMax+1);
        pstNewBitmapEx->pstBitmapEx = pstBitmapEx;
        if (rb_add(&(pstNewBitmapEx->stNode), pstBitmapRbt, RBT_BitmapExCompare))
        {
            // impossible
            free(pstNewBitmapEx);
            return BITMAP_LOC_INVALID_NEW;
        }

        #ifdef __SWIFT_BITMAP__
        print_bitmap_ex(pstNewBitmapEx->uiBitmapID, pstBitmapEx);
        #endif
        pstNewSwift->uiBitmapIDMax++;
    }
    else
    {
        pstNewBitmapEx = rb_entry(pstRbtNode, RBT_BITMAP_EX_S, stNode);
    }

    return pstNewBitmapEx->uiBitmapID;
}

unsigned int append_ipv4_unique_range(IPV4_RANGE_S stKey, struct rb_root* pstRbtUniqueRoot)
{
    RBT_IPV4_MATCH_NODE_S *pstRbtIPv4Node = NULL;
    
    pstRbtIPv4Node = (RBT_IPV4_MATCH_NODE_S *)zalloc(sizeof(RBT_IPV4_MATCH_NODE_S));
    if (NULL == pstRbtIPv4Node)
    {
    	return ERROR_NONE_MEMORY;
    }
    
	pstRbtIPv4Node->stKey = stKey;
	pstRbtIPv4Node->stMatch.uiBitmapID = BITMAP_LOC_INVALID_NEW;
    pstRbtIPv4Node->stMatch.stMatchList = RB_ROOT;
    if (rb_add(&(pstRbtIPv4Node->stNode), pstRbtUniqueRoot, RBT_IPv4MatchNodeCompare))
    {
        free(pstRbtIPv4Node);
    }

    return ERROR_SUCCESS;    
}
    
unsigned int build_ipv4_unique_range(IPV4_RANGE_S stKey, struct rb_root* pstMatchiList,
                                     SWIFT_IPV4_S *pstSwiftIPv4, SWIFT_FWD_S *pstNewSwift)
{
	unsigned int uiRet = ERROR_SUCCESS;
	unsigned int uiBitmapID = BITMAP_LOC_INVALID_NEW;
    RBT_IPV4_MATCH_NODE_S *pstRbtIPv4Node = NULL;
    struct rb_node *pstRbtUniqueNode = NULL;
    struct rb_root *pstRbtUniqueRoot = &(pstSwiftIPv4->stIpv4Match);
    BITMAP_EX_S *pstTemporaryBitmapEx = NULL;
    BITMAP_EX_S *pstFormalBitmapEx = NULL;
    RBT_IPV4_MATCH_NODE_S stUniqueFind;
 
    stUniqueFind.stKey = stKey;
    pstRbtUniqueNode = rb_find(&(stUniqueFind.stNode), pstRbtUniqueRoot, RBT_IPv4MatchNodeCompare);
    if (NULL == pstRbtUniqueNode)
    {
        uiRet = append_ipv4_unique_range(stKey, pstRbtUniqueRoot);
        if (ERROR_SUCCESS != uiRet)
        {
            return uiRet;
        }
        pstRbtUniqueNode = rb_find(&(stUniqueFind.stNode), pstRbtUniqueRoot, RBT_IPv4MatchNodeCompare);
        if (NULL == pstRbtUniqueNode)
        {
            return ERROR_NOT_EXIST;
        }
    }

    pstTemporaryBitmapEx = BITMAP_EX_Create(pstMatchiList);
    if (NULL == pstTemporaryBitmapEx)
    {
        return ERROR_NONE_MEMORY;
    }

    pstFormalBitmapEx = BITMAP_EX_Formalize(pstTemporaryBitmapEx);
    free(pstTemporaryBitmapEx);
    if (NULL == pstFormalBitmapEx)
    {
        return ERROR_NONE_MEMORY;
    }

    uiBitmapID = append_bitmap_ex_to_swift(pstFormalBitmapEx, pstNewSwift);
    if (BITMAP_LOC_INVALID_NEW == uiBitmapID)
    {
        free(pstFormalBitmapEx);
        return ERROR_NONE_MEMORY;
    }
    
    pstRbtIPv4Node = rb_entry(pstRbtUniqueNode, RBT_IPV4_MATCH_NODE_S, stNode);
    pstRbtIPv4Node->stMatch.uiBitmapID = uiBitmapID;
    
    return uiRet;
}

unsigned int convert_ipv4_to_unique_range_set(SWIFT_IPV4_S *pstSwiftIPv4, SWIFT_FWD_S *pstNewSwift)
{
    unsigned int uiRet = ERROR_SUCCESS;
	IPV4_RANGE_S stUniqueRange;
	IPV4_RANGE_S *pstCurrent = NULL;
    struct rb_root stWaitAdjust = RB_ROOT;
	struct rb_node *pstRbtObjectNode = NULL;
	RBT_IPV4_ITEM_S *pstIPv4ItemNode = NULL;
	struct rb_root *pstCfgIPv4List = &pstSwiftIPv4->stCfgIPv4List;

	while ((ERROR_SUCCESS == uiRet) && (true != rb_is_emplty(pstCfgIPv4List)))
    {
        struct rb_root stUniqueMatchList = RB_ROOT;
        
        stUniqueRange = caculate_ipv4_unique_range(pstCfgIPv4List);
        #ifdef __SWIFT_DEBUG__
        {
            char szIpStart[IPV4_MAX_LEN+1] = { 0 };
            char szIpEnd[IPV4_MAX_LEN+1] = { 0 };
            ipv4_to_string(ntohl(stUniqueRange.ipStart), szIpStart, sizeof(szIpStart));
            ipv4_to_string(ntohl(stUniqueRange.ipEnd), szIpEnd, sizeof(szIpEnd));
            LOGGER("[SPLIT] IPV4_UNIQUE_RANGE %s to %s", szIpStart, szIpEnd);
        }
        #endif
        for (pstRbtObjectNode = rb_first(pstCfgIPv4List); pstRbtObjectNode; pstRbtObjectNode = rb_next(pstRbtObjectNode)) 
        {
        	pstIPv4ItemNode = rb_entry(pstRbtObjectNode, RBT_IPV4_ITEM_S, stNode);
        	pstCurrent = &(pstIPv4ItemNode->stAdjustRange);
            if (stUniqueRange.ipEnd >= pstCurrent->ipStart)
            {
                uiRet = append_match_list_to_unique(&(pstIPv4ItemNode->stMatchList), &stUniqueMatchList);
                if (ERROR_SUCCESS != uiRet)
	            {
	                break;
	            }
                
                if ((pstCurrent->ipStart == stUniqueRange.ipStart) &&
                    (pstCurrent->ipEnd == stUniqueRange.ipEnd))
                {
                    pstIPv4ItemNode->uiFlag = 1; //delete
                }
                else
                {
                    pstCurrent->ipStart = stUniqueRange.ipEnd + 1;
                    pstIPv4ItemNode->uiFlag = 0;
                }
                
                uiRet = append_ipv4_to_adjust(&(pstIPv4ItemNode->stKeyRange), &stWaitAdjust);   
				if (ERROR_SUCCESS != uiRet)
	            {
	                break;
	            }
            }
            else
            {
                break;
            }
        }

        if (ERROR_SUCCESS == uiRet)
        {
		    uiRet = build_ipv4_unique_range(stUniqueRange, &stUniqueMatchList, pstSwiftIPv4, pstNewSwift);
        }

        rb_destory(&stUniqueMatchList, RBT_SummaryNodeFree);
        if (ERROR_SUCCESS == uiRet)
        {
			uiRet = adjust_ipv4_cfglist(&stWaitAdjust, pstCfgIPv4List);
        }

        rb_destory(&stWaitAdjust, RBT_Ipv4NodeFree);
    }

    return uiRet;
}

void print_ipv4_unique_range_set(SWIFT_IPV4_S *pstSwiftIPv4, SWIFT_FWD_S *pstNewSwift)
{
    unsigned int uiAnyBitmapID;
    unsigned int uiIPv4BitmapID;
    struct rb_root *pstIpv4Match = NULL;
    struct rb_node *pstRbtNode = NULL;
	RBT_IPV4_MATCH_NODE_S *pstRbtIPv4Node = NULL;
    char szIpStart[IPV4_MAX_LEN+1] = { 0 };
    char szIpEnd[IPV4_MAX_LEN+1] = { 0 };

    uiAnyBitmapID = pstSwiftIPv4->stAnyRoot.uiBitmapID;
    LOGGER("RBT_SCAN ANY: %u", uiAnyBitmapID);

    pstIpv4Match = &(pstSwiftIPv4->stIpv4Match);
    for (pstRbtNode = rb_first(pstIpv4Match); pstRbtNode; pstRbtNode = rb_next(pstRbtNode)) 
	{
		pstRbtIPv4Node = rb_entry(pstRbtNode, RBT_IPV4_MATCH_NODE_S, stNode);
        ipv4_to_string(ntohl(pstRbtIPv4Node->stKey.ipStart), szIpStart, sizeof(szIpStart));
        ipv4_to_string(ntohl(pstRbtIPv4Node->stKey.ipEnd), szIpEnd, sizeof(szIpEnd));
        uiIPv4BitmapID = pstRbtIPv4Node->stMatch.uiBitmapID;
		LOGGER("RBT_SCAN %s to %s: %u", szIpStart, szIpEnd, uiIPv4BitmapID);
    }
}

unsigned int caculate_rule_priority_by_bitmap(BITMAP_S stBitmap)
{
    unsigned int uiPriority = RULE_INVALID_PRIORITY;
    if ((stBitmap.uiLoc > 0) && (0 != stBitmap.uiValue))
    {
        uiPriority = (stBitmap.uiLoc-1) * BIT_COUNT;
        uiPriority += BITMAP_FIRST(stBitmap.uiValue);
    }
    return uiPriority;
}

unsigned int caculate_and_insert_any_bitmap(RULE_MATCH_S *pstRuleMatch, SWIFT_FWD_S *pstNewSwift)
{
	unsigned int uiRet = ERROR_SUCCESS;
	unsigned int uiBitmapID = BITMAP_LOC_INVALID_NEW;
	BITMAP_EX_S *pstTemporaryBitmapEx = NULL;
    BITMAP_EX_S *pstFormalBitmapEx = NULL;

    if (true == rb_is_emplty(&(pstRuleMatch->stMatchList)))
	{
	    pstRuleMatch->uiBitmapID = BITMAP_LOC_INVALID_NEW;
		return ERROR_SUCCESS;
	}

	pstTemporaryBitmapEx = BITMAP_EX_Create(&(pstRuleMatch->stMatchList));
    if (NULL == pstTemporaryBitmapEx)
    {
        return ERROR_NONE_MEMORY;
    }

    rb_destory(&(pstRuleMatch->stMatchList), RBT_SummaryNodeFree);
    
    pstFormalBitmapEx = BITMAP_EX_Formalize(pstTemporaryBitmapEx);
    free(pstTemporaryBitmapEx);
    if (NULL == pstFormalBitmapEx)
    {
        return ERROR_NONE_MEMORY;
    }

    #ifdef __SWIFT_DEBUG__
    LOGGER("[ANY]");
    #endif
    uiBitmapID = append_bitmap_ex_to_swift(pstFormalBitmapEx, pstNewSwift);
    if (BITMAP_LOC_INVALID_NEW == uiBitmapID)
    {
        free(pstFormalBitmapEx);
        return ERROR_NONE_MEMORY;
    }
    
    pstRuleMatch->uiBitmapID = uiBitmapID;
	
	return uiRet;
}

unsigned int collect_all_src_ipv4(RULE_S *pstNode, SWIFT_IPV4_S *pstSwiftIPv4)
{
	unsigned int uiRet = ERROR_SUCCESS;
    struct rb_node *pstRbtNode = NULL;
    RBT_IPV4_S *pstIpv4Node = NULL;
    struct rb_root *pstRbtAnyRoot = NULL;
    struct rb_root *pstSrcIpv4Rbt = NULL;

	pstSrcIpv4Rbt = &(pstNode->stSrcIPv4Rbt);
	if (true == rb_is_emplty(pstSrcIpv4Rbt))
	{
		pstRbtAnyRoot = &(pstSwiftIPv4->stAnyRoot.stMatchList);
		uiRet = append_rule_to_matchlist(pstRbtAnyRoot, pstNode->uiPriority);
		return uiRet;
	}

	for (pstRbtNode = rb_first(pstSrcIpv4Rbt); pstRbtNode; pstRbtNode = rb_next(pstRbtNode)) 
	{
		pstIpv4Node = rb_entry(pstRbtNode, RBT_IPV4_S, stNode);
		uiRet = append_ipv4_to_cfglist(pstNode, pstIpv4Node->stIpv4, &(pstSwiftIPv4->stCfgIPv4List));
		if (ERROR_SUCCESS != uiRet)
        {
            break;
        }
	}

	return uiRet;
}

unsigned int collect_all_dst_ipv4(RULE_S *pstNode, SWIFT_IPV4_S *pstSwiftIPv4)
{
	unsigned int uiRet = ERROR_SUCCESS;
    struct rb_node *pstRbtNode = NULL;
    RBT_IPV4_S *pstIpv4Node = NULL;
    struct rb_root *pstRbtAnyRoot = NULL;
    struct rb_root *pstDstIpv4Rbt = NULL;

	pstDstIpv4Rbt = &(pstNode->stDstIPv4Rbt);
	if (true == rb_is_emplty(pstDstIpv4Rbt))
	{
		pstRbtAnyRoot = &(pstSwiftIPv4->stAnyRoot.stMatchList);
		uiRet = append_rule_to_matchlist(pstRbtAnyRoot, pstNode->uiPriority);
		return uiRet;
	}

	for (pstRbtNode = rb_first(pstDstIpv4Rbt); pstRbtNode; pstRbtNode = rb_next(pstRbtNode)) 
	{
		pstIpv4Node = rb_entry(pstRbtNode, RBT_IPV4_S, stNode);
		uiRet = append_ipv4_to_cfglist(pstNode, pstIpv4Node->stIpv4, &(pstSwiftIPv4->stCfgIPv4List));
		if (ERROR_SUCCESS != uiRet)
        {
            break;
        }
	}

	return uiRet;
}

unsigned int build_swift_for_src_ipv4(SWIFT_FWD_S *pstNewSwift)
{
    unsigned int uiRet = ERROR_SUCCESS;
    SWIFT_IPV4_S *pstSwiftSrcIPv4 = NULL;
    struct list_head *pstRuleList = RULE_LIST();
    RULE_S *pstNode = NULL;
    RULE_S *pstNext = NULL;

    // collect configuration
    pstSwiftSrcIPv4 = pstNewSwift->pstSrcIPv4;
    list_for_each_entry_safe(pstNode, pstNext, pstRuleList, stNode)
    {
        uiRet = collect_all_src_ipv4(pstNode, pstSwiftSrcIPv4);
        if (ERROR_SUCCESS != uiRet)
        {
            break;
        }
    }
    if (ERROR_SUCCESS != uiRet)
    {
        return uiRet;
    }

    #ifdef __SWIFT_DEBUG__
    print_all_ipv4_cfglist("all_src_ipv4", &(pstSwiftSrcIPv4->stCfgIPv4List));
    #endif

    uiRet = caculate_and_insert_any_bitmap(&(pstSwiftSrcIPv4->stAnyRoot), pstNewSwift);
    if (ERROR_SUCCESS != uiRet)
    {
        return uiRet;
    }

    uiRet = convert_ipv4_to_unique_range_set(pstSwiftSrcIPv4, pstNewSwift);
    if (ERROR_SUCCESS != uiRet)
    {
        return uiRet;
    }

    rb_destory(&(pstSwiftSrcIPv4->stCfgIPv4List), RBT_IPv4RangeNodeFree);
    
    #ifdef __SWIFT_DEBUG__
    print_ipv4_unique_range_set(pstSwiftSrcIPv4, pstNewSwift);
    #endif

	return uiRet;    
}

unsigned int build_swift_for_dst_ipv4(SWIFT_FWD_S *pstNewSwift)
{
    unsigned int uiRet = ERROR_SUCCESS;
    SWIFT_IPV4_S *pstSwiftDestIPv4 = NULL;
    struct list_head *pstRuleList = RULE_LIST();
    RULE_S *pstNode = NULL;
    RULE_S *pstNext = NULL;

    // collect configuration
    pstSwiftDestIPv4 = pstNewSwift->pstDestIPv4;
    list_for_each_entry_safe(pstNode, pstNext, pstRuleList, stNode)
    {
        uiRet = collect_all_dst_ipv4(pstNode, pstSwiftDestIPv4);
        if (ERROR_SUCCESS != uiRet)
        {
            break;
        }
    }
    if (ERROR_SUCCESS != uiRet)
    {
        return uiRet;
    }

    #ifdef __SWIFT_DEBUG__
    print_all_ipv4_cfglist("all_dest_ipv4", &(pstSwiftDestIPv4->stCfgIPv4List));
    #endif

    uiRet = caculate_and_insert_any_bitmap(&(pstSwiftDestIPv4->stAnyRoot), pstNewSwift);
    if (ERROR_SUCCESS != uiRet)
    {
        return uiRet;
    }

    uiRet = convert_ipv4_to_unique_range_set(pstSwiftDestIPv4, pstNewSwift);
    if (ERROR_SUCCESS != uiRet)
    {
        return uiRet;
    }

    rb_destory(&(pstSwiftDestIPv4->stCfgIPv4List), RBT_IPv4RangeNodeFree);
    
    #ifdef __SWIFT_DEBUG__
    print_ipv4_unique_range_set(pstSwiftDestIPv4, pstNewSwift);
    #endif

	return uiRet;    
}

unsigned int convert_bitmap_rbt_to_array(SWIFT_FWD_S *pstNewSwift)
{
    unsigned int uiRet = ERROR_SUCCESS;
    unsigned int uiBitmapCountEx;
    struct rb_node *pstRbtNode = NULL;
    BITMAP_EX_S **ppstBitmapArray = NULL;
    RBT_BITMAP_EX_S *pstRbtBitmapEx = NULL;
    
    uiBitmapCountEx = pstNewSwift->uiBitmapIDMax + RESERVED_BITMAP_CNT;
    ppstBitmapArray = (BITMAP_EX_S **)zalloc(uiBitmapCountEx*sizeof(BITMAP_EX_S *));
    if (NULL == ppstBitmapArray)
    {
        return ERROR_NONE_MEMORY;
    }
    
    for (pstRbtNode = rb_first(&(pstNewSwift->stBitmapRbt)); pstRbtNode; pstRbtNode = rb_next(pstRbtNode)) 
    {
        pstRbtBitmapEx = rb_entry(pstRbtNode, RBT_BITMAP_EX_S, stNode);
        if (pstRbtBitmapEx->uiBitmapID < uiBitmapCountEx)
        {
            ppstBitmapArray[pstRbtBitmapEx->uiBitmapID] = pstRbtBitmapEx->pstBitmapEx;
        }
        else
        {
            uiRet = ERROR_OUT_BOUND;
            break;
        }
    }

    if (ERROR_SUCCESS == uiRet)
    {
        pstNewSwift->ppstBitmapArray = ppstBitmapArray;
        rb_destory(&(pstNewSwift->stBitmapRbt), RBT_BitmapExShellFree);
    }
    else
    {
        free(ppstBitmapArray);
    }

    #ifdef __SWIFT_DEBUG__
    print_all_bitmap_ex(pstNewSwift);
    #endif
    
    return uiRet;
}

unsigned int build_new_swift(SWIFT_FWD_S *pstNewSwift)
{
	unsigned int uiRet = ERROR_SUCCESS;
	unsigned int uiKeyMask;

    prepare_new_swift(pstNewSwift);
    uiKeyMask = pstNewSwift->uiKeyMask;
    
    if ((ERROR_SUCCESS == uiRet) && (RULE_KEY_NONE != (uiKeyMask & RULE_KEY_SIP)))
    {
        uiRet = build_swift_for_src_ipv4(pstNewSwift);
    }

    if ((ERROR_SUCCESS == uiRet) && (RULE_KEY_NONE != (uiKeyMask & RULE_KEY_DIP)))
    {
        uiRet = build_swift_for_dst_ipv4(pstNewSwift);
    }

    if (ERROR_SUCCESS == uiRet)
    {
        uiRet = convert_bitmap_rbt_to_array(pstNewSwift);
    }

	return uiRet;
}

void replace_swift(SWIFT_FWD_S *pstNewSwift)
{
    SWIFT_FWD_S *pstOldSwift = g_pstSwiftFwd;
    
    MATCH_LOCK_WRITE();
    g_pstSwiftFwd = pstNewSwift;
    MATCH_UNLOCK();
    
    destroy_swift(pstOldSwift);
}

unsigned int build_swift()
{
    unsigned int uiRet;
    SWIFT_FWD_S *pstNewSwift;

    pstNewSwift = alloc_swift();
    if (NULL == pstNewSwift)
    {
        LOGGER("alloc swift fail!");
        return ERROR_FAILED;
    }

    uiRet = build_new_swift(pstNewSwift);
    if (ERROR_SUCCESS != uiRet)
    {
        destroy_swift(pstNewSwift);
        LOGGER("build swift proc fail!");
        return uiRet;
    }
    
    replace_swift(pstNewSwift);

    return uiRet;
}

unsigned int SWIFT_BUILD()
{
    unsigned int uiRet;

    EDIT_LOCK_READ();
    uiRet = build_swift();
    EDIT_UNLOCK();

    return uiRet;
}

void SWIFT_DESTROY()
{
	destroy_swift(g_pstSwiftFwd);
	g_pstSwiftFwd = NULL;
}

RULE_SUMMARY_S swift_match_src_ipv4(unsigned int uiIPv4)
{
    SWIFT_IPV4_S *pstSrcIPv4;
    RBT_IPV4_MATCH_NODE_S stFind;
    RBT_IPV4_MATCH_NODE_S *pstRbtIPv4;
    struct rb_node *pstRbtNode = NULL;
    unsigned int uiAnyBitmapID;
    unsigned int uiIpv4BitmapID;
    BITMAP_EX_S *pstAnyBitmapEx = NULL;
    BITMAP_EX_S *pstIPv4BitmapEx;
    RULE_SUMMARY_S stNotMatch = MATCH_NONE;
    BITMAP_S stAnyBitmap = { BITMAP_INVALID_LOC, BITMAP_INVALID_VAL };
    BITMAP_S stIPv4Bitmap = { BITMAP_INVALID_LOC, BITMAP_INVALID_VAL };
    BITMAP_S stMatchBitmap = { BITMAP_INVALID_LOC, BITMAP_INVALID_VAL };
    unsigned int uiPriority = RULE_INVALID_PRIORITY;

    if (NULL == g_pstSwiftFwd)
    {
        return stNotMatch;
    }

    pstSrcIPv4 = g_pstSwiftFwd->pstSrcIPv4;
    if (NULL == pstSrcIPv4)
    {
        return stNotMatch;
    }

    uiAnyBitmapID = pstSrcIPv4->stAnyRoot.uiBitmapID;
    if (uiAnyBitmapID <= g_pstSwiftFwd->uiBitmapIDMax)
    {
        pstAnyBitmapEx = g_pstSwiftFwd->ppstBitmapArray[uiAnyBitmapID];
        if ((NULL != pstAnyBitmapEx) && (pstAnyBitmapEx->uiCount > 0))      
        {
            stAnyBitmap = pstAnyBitmapEx->astBitmap[0];
        }
    }

    stFind.stKey.ipStart = uiIPv4;
	stFind.stKey.ipEnd = uiIPv4;
	pstRbtNode = rb_find(&(stFind.stNode), &(pstSrcIPv4->stIpv4Match), RBT_IPv4MatchRange);
	if (NULL != pstRbtNode)
	{
		pstRbtIPv4 = rb_entry(pstRbtNode, RBT_IPV4_MATCH_NODE_S, stNode);
        uiIpv4BitmapID = pstRbtIPv4->stMatch.uiBitmapID;
        if (uiIpv4BitmapID <= g_pstSwiftFwd->uiBitmapIDMax)
        {
            pstIPv4BitmapEx = g_pstSwiftFwd->ppstBitmapArray[uiIpv4BitmapID];
            if ((NULL != pstIPv4BitmapEx) && (pstIPv4BitmapEx->uiCount > 0))      
            {
                stIPv4Bitmap = pstIPv4BitmapEx->astBitmap[0];
            }
        }
	}

    if (BITMAP_INVALID_VAL == stAnyBitmap.uiValue)
	{
	    if (BITMAP_INVALID_VAL == stIPv4Bitmap.uiValue)
	    {
	        return stNotMatch;
	    }
	    else
	    {
	        stMatchBitmap = stIPv4Bitmap;
	    }
	}
	else
	{
	    if (BITMAP_INVALID_VAL == stIPv4Bitmap.uiValue)
	    {
	        stMatchBitmap = stAnyBitmap;
	    }
	    else
	    {
	        if (stAnyBitmap.uiLoc < stIPv4Bitmap.uiLoc)
            {
                stMatchBitmap = stAnyBitmap;
            }
            else if (stAnyBitmap.uiLoc > stIPv4Bitmap.uiLoc)
            {
                stMatchBitmap = stIPv4Bitmap;
            }
            else
            {
                stMatchBitmap = stAnyBitmap;
                stMatchBitmap.uiValue |= stIPv4Bitmap.uiValue;
            }
	    }
	}
	
    uiPriority = caculate_rule_priority_by_bitmap(stMatchBitmap);
    if (uiPriority <= g_pstSwiftFwd->uiRuleCount)
    {
        return g_pstSwiftFwd->pstRuleArray[uiPriority];
    }
    
	return stNotMatch;
}

RULE_SUMMARY_S SWIFT_MATCH_SRC_IPV4(unsigned int uiIPv4)
{
    RULE_SUMMARY_S stObjMatch;
    
    MATCH_LOCK_READ();
    stObjMatch = swift_match_src_ipv4(uiIPv4);
    MATCH_UNLOCK();

    return stObjMatch;
}

RULE_SUMMARY_S swift_match_dst_ipv4(unsigned int uiIPv4)
{
    SWIFT_IPV4_S *pstDestIPv4;
    RBT_IPV4_MATCH_NODE_S stFind;
    RBT_IPV4_MATCH_NODE_S *pstRbtIPv4;
    struct rb_node *pstRbtNode = NULL;
    unsigned int uiAnyBitmapID;
    unsigned int uiIpv4BitmapID;
    BITMAP_EX_S *pstAnyBitmapEx = NULL;
    BITMAP_EX_S *pstIPv4BitmapEx;
    RULE_SUMMARY_S stNotMatch = MATCH_NONE;
    BITMAP_S stAnyBitmap = { BITMAP_INVALID_LOC, BITMAP_INVALID_VAL };
    BITMAP_S stIPv4Bitmap = { BITMAP_INVALID_LOC, BITMAP_INVALID_VAL };
    BITMAP_S stMatchBitmap = { BITMAP_INVALID_LOC, BITMAP_INVALID_VAL };
    unsigned int uiPriority = RULE_INVALID_PRIORITY;

    if (NULL == g_pstSwiftFwd)
    {
        return stNotMatch;
    }

    pstDestIPv4 = g_pstSwiftFwd->pstDestIPv4;
    if (NULL == pstDestIPv4)
    {
        return stNotMatch;
    }

    uiAnyBitmapID = pstDestIPv4->stAnyRoot.uiBitmapID;
    if (uiAnyBitmapID <= g_pstSwiftFwd->uiBitmapIDMax)
    {
        pstAnyBitmapEx = g_pstSwiftFwd->ppstBitmapArray[uiAnyBitmapID];
        if ((NULL != pstAnyBitmapEx) && (pstAnyBitmapEx->uiCount > 0))      
        {
            stAnyBitmap = pstAnyBitmapEx->astBitmap[0];
        }
    }

    stFind.stKey.ipStart = uiIPv4;
	stFind.stKey.ipEnd = uiIPv4;
	pstRbtNode = rb_find(&(stFind.stNode), &(pstDestIPv4->stIpv4Match), RBT_IPv4MatchRange);
	if (NULL != pstRbtNode)
	{
		pstRbtIPv4 = rb_entry(pstRbtNode, RBT_IPV4_MATCH_NODE_S, stNode);
        uiIpv4BitmapID = pstRbtIPv4->stMatch.uiBitmapID;
        if (uiIpv4BitmapID <= g_pstSwiftFwd->uiBitmapIDMax)
        {
            pstIPv4BitmapEx = g_pstSwiftFwd->ppstBitmapArray[uiIpv4BitmapID];
            if ((NULL != pstIPv4BitmapEx) && (pstIPv4BitmapEx->uiCount > 0))      
            {
                stIPv4Bitmap = pstIPv4BitmapEx->astBitmap[0];
            }
        }
	}

    if (BITMAP_INVALID_VAL == stAnyBitmap.uiValue)
	{
	    if (BITMAP_INVALID_VAL == stIPv4Bitmap.uiValue)
	    {
	        return stNotMatch;
	    }
	    else
	    {
	        stMatchBitmap = stIPv4Bitmap;
	    }
	}
	else
	{
	    if (BITMAP_INVALID_VAL == stIPv4Bitmap.uiValue)
	    {
	        stMatchBitmap = stAnyBitmap;
	    }
	    else
	    {
	        if (stAnyBitmap.uiLoc < stIPv4Bitmap.uiLoc)
            {
                stMatchBitmap = stAnyBitmap;
            }
            else if (stAnyBitmap.uiLoc > stIPv4Bitmap.uiLoc)
            {
                stMatchBitmap = stIPv4Bitmap;
            }
            else
            {
                stMatchBitmap = stAnyBitmap;
                stMatchBitmap.uiValue |= stIPv4Bitmap.uiValue;
            }
	    }
	}
	
    uiPriority = caculate_rule_priority_by_bitmap(stMatchBitmap);
    if (uiPriority <= g_pstSwiftFwd->uiRuleCount)
    {
        return g_pstSwiftFwd->pstRuleArray[uiPriority];
    }
    
	return stNotMatch;
}

RULE_SUMMARY_S SWIFT_MATCH_DEST_IPV4(unsigned int uiIPv4)
{
    RULE_SUMMARY_S stObjMatch;
    
    MATCH_LOCK_READ();
    stObjMatch = swift_match_dst_ipv4(uiIPv4);
    MATCH_UNLOCK();

    return stObjMatch;
}

void __attribute__((constructor(PRIORITY_SWIFT))) SWIFT_INIT()
{
    MATCH_LOCK_INIT();  
}

void __attribute__((destructor(PRIORITY_SWIFT))) SWIFT_EXIT()
{
    SWIFT_DESTROY();
    MATCH_LOCK_DESTROY();
}

